package com.fin.zw.intelligentbot.service;


import com.fin.zw.intelligentbot.entity.*;
import com.fin.zw.intelligentbot.enums.TaskStatus;
import com.fin.zw.intelligentbot.model.request.StatisticLogRequest;
import com.fin.zw.intelligentbot.model.response.CategoryLabelResponse;
import com.fin.zw.intelligentbot.model.response.StatisticCategoryResponse;
import com.fin.zw.intelligentbot.model.response.StatisticCustomerResponse;
import com.fin.zw.intelligentbot.model.session.SessionModel;
import com.fin.zw.intelligentbot.repository.CategoryLabelRepository;
import com.fin.zw.intelligentbot.repository.SceneInfoRepository;
import com.fin.zw.intelligentbot.repository.TaskCustomerRepository;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service("statisticService")
public class StatisticService {
    private final Logger log = LoggerFactory.getLogger(StatisticService.class);

    @Autowired
    private TaskCustomerRepository taskCustomerRepository;

    @Autowired
    private CategoryLabelRepository categoryLabelRepository;

    @Autowired
    private CommonService commonService;

    @Autowired
    private SceneInfoRepository sceneInfoRepository;

    /**
     * 统计近30天的日志记录
     *
     * @param request
     * @param sessionModel
     * @return
     * @throws Exception
     */
    public List<StatisticCustomerResponse> statisticsCustomerByDate(StatisticLogRequest request, SessionModel sessionModel) throws Exception {
        List<StatisticCustomerResponse> list = new ArrayList<>();
        BooleanBuilder builder = new BooleanBuilder();
        if (StringUtils.isNotEmpty(sessionModel.getCompanyId())) {
            builder.and(QTaskCustomer.taskCustomer.company.id.eq(sessionModel.getCompanyId()));
        }
        //getBooleanBuilder(request,sessionModel);
        Date old = DateTime.now().minusDays(9).toDate();//获取10天以前的时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        builder.and(QTaskCustomer.taskCustomer.createTime.after(old));
        Iterator<TaskCustomer> iterator = taskCustomerRepository.findAll(builder).iterator();
        List<TaskCustomer> taskCustomers = Lists.newArrayList(iterator);
        Map<String, List<TaskCustomer>> map = new HashMap<>();
        for (int i = 0; i < 10; i++) {
            Date key = DateTime.now().minusDays(i).toDate();
            List<TaskCustomer> customers = new ArrayList<>();
            map.put(df.format(key), customers);
        }
        taskCustomers.forEach(taskCustomer -> {
            String date = df.format(taskCustomer.getCreateTime());
            List<TaskCustomer> customers = map.get(date);
            customers.add(taskCustomer);
            map.put(date, customers);
        });
        for (Map.Entry<String, List<TaskCustomer>> entry : map.entrySet()) {
            StatisticCustomerResponse response = new StatisticCustomerResponse();
            response.setDate(entry.getKey());
            setCustomerResponse(entry.getValue(), response);
            list.add(response);
        }
        Collections.sort(list, Comparator.comparing(StatisticCustomerResponse::getDate));
        return list;
    }

    /**
     * 对返回数据进行组装
     *
     * @param customerList
     * @param response
     */
    public void setCustomerResponse(List<TaskCustomer> customerList, StatisticCustomerResponse response) {
        response.setPhoneNumber(customerList.size());
        Integer callNumber = 0;//呼叫数量
        Integer connectNumber = 0;//接通数量
        Integer totalTime = 0;//通话时长
        Integer callTime = 0;//呼叫时长
        for (TaskCustomer c : customerList) {
            if (!c.getStatus().equals(TaskStatus.NEW)
                    && !c.getStatus().equals(TaskStatus.READY)) { //呼叫数量
                callNumber++;
                if (c.getDuration() != null) {
                    callTime += c.getDuration();//计算呼叫时长
                }
                if (c.getStatus().equals(TaskStatus.CONNECTED)) {//已接通
                    connectNumber++;
                    if (c.getBillTime() != null) {
                        totalTime += c.getBillTime();
                    }
                }
            }
        }
        response.setCallNumber(callNumber);
        response.setConnectNumber(connectNumber);
        response.setTotalTime(totalTime);
        response.setCallTime(callTime);
        if (connectNumber == 0) {
            response.setAverageTime(0);
        } else {
            response.setAverageTime(totalTime / connectNumber);
        }
        if (callNumber == 0) {
            response.setConnectRatio(0D);
        } else {
            Double connectRatio = Double.valueOf(connectNumber) / callNumber;
            response.setConnectRatio(connectRatio);
        }
    }

    /**
     * 根据任务进行统计日志
     *
     * @param request
     * @param sessionModel
     * @return
     * @throws Exception
     */
    public List<StatisticCustomerResponse> statisticsCustomerByTask(StatisticLogRequest request, SessionModel sessionModel) {
        List<StatisticCustomerResponse> list = new ArrayList<>();
        BooleanBuilder builder = getBooleanBuilder(request, sessionModel);
        Iterator<TaskCustomer> iterator = taskCustomerRepository.findAll(builder).iterator();
        List<TaskCustomer> taskCustomers = Lists.newArrayList(iterator);
        Map<DialTask, List<TaskCustomer>> map = taskCustomers.stream().collect(Collectors.groupingBy(TaskCustomer::getDialTask));
        for (Map.Entry<DialTask, List<TaskCustomer>> entry : map.entrySet()) {
            StatisticCustomerResponse response = new StatisticCustomerResponse();
            response.setTaskName(entry.getKey().getName());
            setCustomerResponse(entry.getValue(), response);
            list.add(response);
        }
        return list;
    }


    /**
     * 按照时间段进行分组查询
     *
     * @param sessionModel
     * @return
     */
    public List<StatisticCustomerResponse> statisticsByTimeHour(SessionModel sessionModel) {
        List<StatisticCustomerResponse> list = new ArrayList<>();
        Date old = DateTime.now().minusDays(29).toDate();//获取30天以前的时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < 12; i++) {
            StatisticCustomerResponse response = new StatisticCustomerResponse();
            String start = (8 + i) + ":00:00";
            String end = (8 + 1 + i) + ":00:00";
            response.setTime(start);
            List<TaskCustomer> taskCustomers = new ArrayList<>();
            if (StringUtils.isNotEmpty(sessionModel.getCompanyId())) {
                taskCustomers = taskCustomerRepository.getInfoByTime(df.format(old), sessionModel.getCompanyId(), start, end);
            } else {
                taskCustomers = taskCustomerRepository.getInfoByTime(df.format(old), start, end);
            }
            if (taskCustomers != null && !taskCustomers.isEmpty()) {
                response.setPhoneNumber(taskCustomers.size());
                setCustomerResponse(taskCustomers, response);
            } else {
                response.setPhoneNumber(0);//号码数量
                response.setConnectRatio(0D);//接通率
                response.setAverageTime(0);//平均通话时长
                response.setCallTime(0);//呼叫时长
                response.setTotalTime(0);//通话时长
                response.setConnectNumber(0);//接通数量
                response.setCallNumber(0);//呼叫数量
            }
            list.add(response);
        }

        return list;
    }

    /**
     * 根据场景统计日志信息
     *
     * @param request
     * @param sessionModel
     * @return
     */
    public List<StatisticCustomerResponse> statisticsCustomerBySce(StatisticLogRequest request, SessionModel sessionModel) {
        List<StatisticCustomerResponse> list = new ArrayList<>();
        BooleanBuilder builder = getBooleanBuilder(request, sessionModel);
        Iterator<TaskCustomer> iterator = taskCustomerRepository.findAll(builder).iterator();
        List<TaskCustomer> taskCustomers = Lists.newArrayList(iterator);
        Map<SceneInfo, List<TaskCustomer>> map = getSceneInfoListMap(taskCustomers);
        for (Map.Entry<SceneInfo, List<TaskCustomer>> entry : map.entrySet()) {
            StatisticCustomerResponse response = new StatisticCustomerResponse();
            response.setSceName(entry.getKey().getName());
            setCustomerResponse(entry.getValue(), response);
            list.add(response);
        }
        return list;
    }

    /**
     * 对场景信息进行组装
     *
     * @param taskCustomers
     * @return
     */
    public Map<SceneInfo, List<TaskCustomer>> getSceneInfoListMap(List<TaskCustomer> taskCustomers) {
        Map<SceneInfo, List<TaskCustomer>> map = new HashMap<>();
        taskCustomers.forEach(customer -> {
            if (Objects.nonNull(customer.getDialTask())) {
                if (map.containsKey(customer.getDialTask().getScene())) {
                    List<TaskCustomer> customerList = map.get(customer.getDialTask().getScene());
                    customerList.add(customer);
                    map.put(customer.getDialTask().getScene(), customerList);
                } else {
                    List<TaskCustomer> customerList = new ArrayList<>();
                    customerList.add(customer);
                    map.put(customer.getDialTask().getScene(), customerList);
                }
            }
        });
        return map;
    }

    /**
     * 统计的查询条件
     *
     * @param request
     * @param sessionModel
     * @return
     */
    public BooleanBuilder getBooleanBuilder(StatisticLogRequest request, SessionModel sessionModel) {
        BooleanBuilder builder = new BooleanBuilder();
        QTaskCustomer qTaskCustomer = QTaskCustomer.taskCustomer;
        if (StringUtils.isNotEmpty(sessionModel.getCompanyId())) {
            builder.and(qTaskCustomer.company.id.eq(sessionModel.getCompanyId()));
        }
        builder.and(qTaskCustomer.attitude.isNotNull());
        if (StringUtils.isNotEmpty(request.getTaskId())) {
            builder.and(qTaskCustomer.dialTask.id.eq(request.getTaskId()));
        }
        if (StringUtils.isNotEmpty(request.getSceId())) {
            builder.and(qTaskCustomer.dialTask.scene.id.eq(request.getSceId()));
        }
        if (request.getStartTime() != null && request.getEndTime() != null) {
            builder.and(qTaskCustomer.createTime.between(request.getStartTime(), request.getEndTime()));
        }
        return builder;
    }

    /**
     * 统计场景的未接通客户分类
     *
     * @param request
     * @param taskStatus
     * @param sessionModel
     * @return
     */
    public List<StatisticCategoryResponse> getSceUnconnected(StatisticLogRequest request, TaskStatus taskStatus, SessionModel sessionModel) {
        List<StatisticCategoryResponse> list = new ArrayList<>();
        if (StringUtils.isNotEmpty(sessionModel.getCompanyId())) {
            Company company = commonService.getCompany(sessionModel);
            List<TaskCustomer> taskCustomers = getTaskCustomerList(request, taskStatus, sessionModel);
            Iterator<SceneInfo> iterator = sceneInfoRepository.findAll(QSceneInfo.sceneInfo.companies.contains(company)).iterator();
            Map<SceneInfo, List<TaskCustomer>> map = getSceneInfoListMap(taskCustomers);
            while (iterator.hasNext()) {
                SceneInfo sceneInfo = iterator.next();
                if (map.containsKey(sceneInfo)) {
                    list.add(getCategoryLabelResponse(sceneInfo, map.get(sceneInfo), taskStatus, company));
                } else {
                    list.add(getCategoryLabelResponse(sceneInfo, new ArrayList<>(), taskStatus, company));
                }
            }
        }
        return list;
    }

    public StatisticCategoryResponse getCategoryLabelResponse(SceneInfo sceneInfo, List<TaskCustomer> customers, TaskStatus taskStatus, Company company) {
        StatisticCategoryResponse response = new StatisticCategoryResponse();
        response.setSceName(sceneInfo.getName());
        response.setTotal(customers.size());
        Iterator<CategoryLabel> iterator = categoryLabelRepository.findAll(QCategoryLabel.categoryLabel.companies.contains(company)).iterator();
        List<CategoryLabel> categoryLabelList = Lists.newArrayList(iterator);
        List<CategoryLabel> categorys = new ArrayList<>();
        if (taskStatus.equals(TaskStatus.CONNECTED)) {//接通
            categoryLabelList.forEach(e -> {
                if (Integer.valueOf(e.getCode()) >= 5000) {
                    categorys.add(e);
                }
            });
        } else if (taskStatus.equals(TaskStatus.UNCONNECTED)) {//未接通
            categoryLabelList.forEach(e -> {
                if (Integer.valueOf(e.getCode()) >= 1000
                        && Integer.valueOf(e.getCode()) <= 1500) {
                    categorys.add(e);
                }
            });
        }
        List<CategoryLabelResponse> categories = getCategoryLabelResponse(categorys, customers);
        response.setCategories(categories);
        return response;
    }

    public List<CategoryLabelResponse> getCategoryLabelResponse(List<CategoryLabel> list, List<TaskCustomer> customers) {
        List<CategoryLabelResponse> cateList = new ArrayList<>();
        Map<String, CategoryLabelResponse> codeMap = new HashMap<>();
        list.forEach(e -> {
            CategoryLabelResponse response = new CategoryLabelResponse();
            response.setRatio(0D);
            response.setNumber(0);
            response.setName(e.getName());
            response.setCode(e.getCode());
            codeMap.put(e.getCode(), response);
        });
        for (TaskCustomer c : customers) {
            CategoryLabel cate = c.getAttitude();
            if (Objects.nonNull(cate)
                    && codeMap.containsKey(cate.getCode())) {
                CategoryLabelResponse res = codeMap.get(cate.getCode());
                res.setNumber(res.getNumber() + 1);
                Double ratio = Double.valueOf(res.getNumber()) / customers.size();
                res.setRatio(ratio);
                codeMap.put(cate.getCode(), res);
            }
        }
        for (Map.Entry<String, CategoryLabelResponse> label : codeMap.entrySet()) {
            cateList.add(label.getValue());
        }
        return cateList;
    }

    /**
     * 统计任务的未接通客户分类
     *
     * @param request
     * @param taskStatus
     * @param sessionModel
     * @return
     */
    public List<StatisticCategoryResponse> getTaskUnconnected(StatisticLogRequest request, TaskStatus taskStatus, SessionModel sessionModel) {
        List<StatisticCategoryResponse> list = new ArrayList<>();
        List<TaskCustomer> taskCustomers = getTaskCustomerList(request, taskStatus, sessionModel);
        Map<DialTask, List<TaskCustomer>> map = taskCustomers.stream().collect(Collectors.groupingBy(TaskCustomer::getDialTask));
        for (Map.Entry<DialTask, List<TaskCustomer>> entry : map.entrySet()) {
            StatisticCategoryResponse response = new StatisticCategoryResponse();
            response.setTaskName(entry.getKey().getName());
            getStatisticCategoryResponse(entry.getValue(), response);
            list.add(response);
        }
        return list;
    }

    /**
     * 对客户分类进行统计
     *
     * @param customers
     * @param response
     * @return
     */
    public StatisticCategoryResponse getStatisticCategoryResponse(List<TaskCustomer> customers, StatisticCategoryResponse response) {
        response.setTotal(customers.size());
        List<CategoryLabelResponse> responseList = new ArrayList<>();
        Map<String, CategoryLabelResponse> codeMap = new HashMap<>();
        for (TaskCustomer c : customers) {
            CategoryLabel cate = c.getAttitude();
            if (Objects.nonNull(cate)) {
                if (codeMap.containsKey(cate.getCode())) {
                    CategoryLabelResponse res = codeMap.get(cate.getCode());
                    res.setNumber(res.getNumber() + 1);
                    Double ratio = Double.valueOf(res.getNumber()) / customers.size();
                    res.setRatio(ratio);
                    codeMap.put(cate.getCode(), res);
                } else {
                    CategoryLabelResponse res = new CategoryLabelResponse();
                    res.setCode(cate.getCode());
                    res.setName(cate.getName());
                    res.setNumber(1);
                    res.setRatio(1D);
                    codeMap.put(cate.getCode(), res);
                }
            }
        }
        for (Map.Entry<String, CategoryLabelResponse> label : codeMap.entrySet()) {
            responseList.add(label.getValue());
        }
        response.setCategories(responseList);
        return response;
    }


    public List<TaskCustomer> getTaskCustomerList(StatisticLogRequest request, TaskStatus taskStatus, SessionModel sessionModel) {
        BooleanBuilder builder = getBooleanBuilder(request, sessionModel);
        builder.and(QTaskCustomer.taskCustomer.status.eq(taskStatus));
        Iterator<TaskCustomer> iterator = taskCustomerRepository.findAll(builder).iterator();
        return Lists.newArrayList(iterator);
    }
}
